import re
from django.contrib.auth.models import User
from rest_framework import serializers
from rest_framework.serializers import ModelSerializer, Serializer
from rest_framework_simplejwt.serializers import TokenObtainSlidingSerializer
from django_redis import get_redis_connection
from config.dbs.redisconfig import LOGIN_KEY_TEMPLATE
from user.models import UserDetail, Area, Address


class UserDetailSerializer(ModelSerializer):
    class Meta:
        model = UserDetail
        fields = '__all__'
        extra_kwargs = {
            'user': {'write_only': True},
            'avatar': {'read_only': True},  # 头像由另外接口页面修改，因此不允许在用户详情页面直接修改
        }


class UserSerializer(ModelSerializer):
    userdetail = UserDetailSerializer(required=False, read_only=True)  # 在user页面增加用户详情userdetail信息

    class Meta:
        model = User
        exclude = ['password', 'last_name', 'user_permissions']
        # fields = '__all__'
        extra_kwargs = {
            'last_login': {'read_only': True},
            'is_superuser': {'read_only': True},
            'is_staff': {'read_only': True},
            'is_active': {'read_only': True},
            'date_joined': {'read_only': True},
            'groups': {'read_only': True}
        }


class MyTokenSerializer(TokenObtainSlidingSerializer):
    def validate(self, attrs):
        data = super().validate(attrs)
        data['id'] = self.user.id
        data['username'] = self.user.username
        # 把头像信息传判断user有没有userdetail这个属性，有则把user.userdetail.avatar传给变量，没有则传None
        data['avatar'] = self.user.userdetail.avatar if hasattr(self.user, 'userdetail') else None

        # 图形验证码校验
        # 1.拿到传入的验证码，如果没有则返回“请输入验证码”
        uuid = self.initial_data.get('uuid')
        verify = self.initial_data.get('verify')
        if not uuid or not verify:
            return {'msg': '请输入验证码'}

        # 2.获取缓存code
        cache = get_redis_connection(alias='verify_codes')
        redis_verify = cache.get(LOGIN_KEY_TEMPLATE % uuid)
        cache.delete(LOGIN_KEY_TEMPLATE % uuid)  # 及时释放redis空间
        if not redis_verify:
            return {'msg': '验证码过期'}

        # 3.如果没有过期比较2个码是否一样
        if redis_verify.lower() != verify.lower():
            return {'msg': '验证码错误'}

        return data


class CreateUserSerializer(ModelSerializer):
    class Meta:
        model = User
        fields = ['username', 'first_name', 'email']
        # extra_kwargs:给指定属性添加或者修改参数
        extra_kwargs = {
            'first_name': {'required': True},  # 重写first_name字段，必须强制要求填写
            'email': {'required': True},  # 重写email字段，必须强制要求填写
        }


class UpdatePasswordSerializer(Serializer):
    password = serializers.CharField(max_length=60, label='旧密码')
    new_password = serializers.CharField(max_length=60, label='新密码')
    repeat_password = serializers.CharField(max_length=60, label='确认密码')

    def validate(self, attrs):
        if attrs['new_password'] != attrs['repeat_password']:
            raise serializers.ValidationError('两次输入的密码不一致')
        return attrs


class AreaSerializer(ModelSerializer):
    class Meta:
        model = Area
        exclude = ['parent']
        # fields = '__all__'
        # extra_kwargs = {}


class ParentSerializer(ModelSerializer):
    area_set = AreaSerializer(many=True, read_only=True)

    class Meta:
        model = Area
        # exclude = ['parent']
        fields = ['id', 'name', 'area_set']
        # extra_kwargs = {}


class AddressSerializer(ModelSerializer):
    province_name = serializers.CharField(source='province.name', read_only=True)
    city_name = serializers.CharField(source='city.name', read_only=True)
    district_name = serializers.CharField(source='district.name', read_only=True)

    class Meta:
        model = Address
        exclude = ['is_delete']
        # fields = '__all__'
        extra_kwargs = {
            'province': {'write_only': True},
            'city': {'write_only': True},
            'district': {'write_only': True},
        }

    def validate_phone(self, attrs):
        if not re.match(r'1[3-9]\d{9}', attrs):
            raise serializers.ValidationError('手机号码错误')
        return attrs
